use std::fs::File;
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::ops::Add;
use std::string::ToString;
use std::thread;
use crate::config::configuration::Config;
use crate::request::method::Method;
use crate::request::request::HttpRequest;
use crate::threadpool::thread_pool::ThreadPool;


//#[derive(Debug)]
pub struct Server {
    host        :       String,
    port        :       String,
    config      :       Config,
    thread_pool :       ThreadPool,
}

const HOST_DEFAULT: &str = "127.0.0.1";
const PORT_DEFAULT: &str = "8081";

impl Server {
    pub fn new(host:String, port: String, config: Config) -> Server{
        let work_station = Self::build_thread_pool(&config);

        let mut server = Server{host, port, config, thread_pool:work_station };
        if server.host.is_empty(){
            server.host = HOST_DEFAULT.to_string();
        }
        if server.port.is_empty() {
            server.port = PORT_DEFAULT.to_string();
        }
        server
    }

    fn build_thread_pool(config: &Config) -> ThreadPool {

        let mut work_station = ThreadPool::new(config);
        work_station.delivery_task();
        work_station
    }

    pub fn run(&self){

        let listener  = TcpListener::bind(self.host.clone()+":"+self.port.clone().as_str()).unwrap();
        for stream in listener.incoming() {
            match stream {
                Ok(mut _stream) => {
                    println!("Start...");
                    self.handle_connection(_stream);
                },
                Err(e) => {
                    eprintln!("Can't start the Tractors, because of the error {}", e);
                }
            }
        }
    }

    fn handle_connection(&self, mut stream: TcpStream) {


        thread::spawn(move ||  {
           // stream.set_nonblocking(true).expect("set non blocking false");
            println!("handle connection");
            //let mut buf_reader = BufReader::new(&mut stream);
            let http_request = HttpRequest::parse_request(&stream);
            println!("after parse request: {:?}", http_request);
            match http_request.method {
                Method::GET => {
                    println!("{}", "recive param");
                    println!("{:?}", http_request);
                    stream.write_all(b"hello");
                }
                Method::POST => {
                    println!("{}", "recive param");
                     println!("{:?}", http_request);
                    stream.write_all(b"hello");
                }
                Method::PUT => {}
                Method::DELETE => {}
                Method::PATCH => {}
                Method::OPTIONS => {}
                Method::HEAD => {}
                Method::CONNECT => {}
                Method::TRACE => {}
                Method::UNIDENTIFIED => {}
            }
            

       });

    }



    pub fn run_in_thread_pool(&mut self){

        let listener  = TcpListener::bind(self.host.clone()+":"+self.port.clone().as_str()).unwrap();
        for stream in listener.incoming() {
            match stream {
                Ok(mut _stream) => {
                    println!("server has received request....");
                    let _ = &self.handle_connection_in_thread_pool(_stream);
                },
                Err(e) => {
                    eprintln!("Can't start the Tractors, because of the error {}", e);
                }
            }
        }
    }

    fn handle_connection_in_thread_pool(&mut self, stream: TcpStream) {
        /*
        let f = || {
            println!("i am a closure")
        };
        &self.thread_pool.execute(move|| f());
        */



        let f  = move |mut stream|  {
            // stream.set_nonblocking(true).expect("set non blocking false");
            println!("handle connection");
            //let mut buf_reader = BufReader::new(&mut stream);
            let http_request = HttpRequest::parse_request(&stream);
            println!("after parse request: {:?}", http_request);
            match http_request.method {
                Method::GET => {
                    println!("{}", "recive param");
                    println!("{:?}", http_request);


                    let mut f = File::open("/home/owen/me.html").unwrap();
                    let mut http = String::new();
                    http = http.add("HTTP/1.1 200 Ok \r\n");
                    http = http.add("Content-Type: text/html; charset=utf-8\r\n");
                    http = http.add("\r\n");

                    let mut content = String::new();
                    f.read_to_string(&mut content);
                    http = http.add(&*content);
                    stream.write(http.as_ref());
                }
                Method::POST => {

                    println!("{:?}", http_request);

                }
                Method::PUT => {}
                Method::DELETE => {}
                Method::PATCH => {}
                Method::OPTIONS => {}
                Method::HEAD => {}
                Method::CONNECT => {}
                Method::TRACE => {}
                Method::UNIDENTIFIED => {}
            }


        };

        let _ = &self.thread_pool.execute(move|| f(stream));
    }
}
